#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
行业股票技术面分析工具
使用 AKShare 获取数据，分析各行业的技术面表现，找出最适合投资的行业

作者: Claude
日期: 2024-05-14
"""

import os
import datetime
import time
import json
import logging
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import akshare as ak
from tqdm import tqdm

import config
from utils import (
    setup_logger, save_to_csv, get_date_range, retry, 
    classify_score, get_score_color, ensure_numeric, format_date
)
from technical_analysis import TechnicalAnalyzer

# 设置日志
logger = setup_logger('industry_analysis', 'logs/industry_analysis.log', 
                     level=getattr(logging, config.LOG_CONFIG['level']))

class IndustryAnalysis:
    def __init__(self, data_dir=config.DATA_DIR, report_dir=config.REPORT_DIR):
        """初始化分析器"""
        self.data_dir = data_dir
        self.report_dir = report_dir
        
        # 创建必要的目录
        for directory in [data_dir, report_dir, 'logs']:
            if not os.path.exists(directory):
                os.makedirs(directory)
                
        # 设置日期格式
        self.today = datetime.datetime.now().strftime(config.REPORT_CONFIG['date_format'])
        start_date, end_date = get_date_range(days=config.HISTORICAL_DAYS)
        self.date_start = start_date
        self.date_end = end_date
        
        # 初始化技术分析器
        self.tech_analyzer = TechnicalAnalyzer()
        
        logger.info(f"分析日期区间: {self.date_start} 至 {self.date_end}")
        print(f"分析日期: {self.today}")
    
    @retry(max_tries=config.API_CONFIG['retry_times'], delay=config.API_CONFIG['request_delay'])
    def get_industry_list(self):
        """获取所有一级行业列表"""
        logger.info("正在获取行业列表...")
        print("正在获取行业列表...")
        try:
            # 使用AKShare获取申万一级行业列表
            industry_df = ak.sw_index_first_info()
            # 已经是申万一级行业，不需要筛选
            industry_list = industry_df.copy()
            
            # 保存到CSV文件
            file_path = f"{self.data_dir}/sw_industry_list_{self.today}.csv"
            save_to_csv(industry_list, file_path)
            logger.info(f"成功获取 {len(industry_list)} 个申万一级行业")
            print(f"成功获取 {len(industry_list)} 个申万一级行业")
            return industry_list
        except Exception as e:
            logger.error(f"获取行业列表出错: {e}")
            print(f"获取行业列表出错: {e}")
            return pd.DataFrame()
    
    @retry(max_tries=config.API_CONFIG['retry_times'], delay=config.API_CONFIG['request_delay'])
    def get_industry_history(self, industry_code, industry_name):
        """获取行业指数历史数据
        
        Args:
            industry_code: 行业代码，如 "801010.SI"
            industry_name: 行业名称
            
        Returns:
            DataFrame: 行业历史数据
        """
        logger.info(f"正在获取行业 {industry_name}({industry_code}) 的历史数据...")
        print(f"正在获取行业 {industry_name}({industry_code}) 的历史数据...")
        
        try:
            # 处理行业代码格式（去掉.SI后缀）
            if '.' in industry_code:
                code = industry_code.split('.')[0]
            else:
                code = industry_code
                
            # 使用AKShare获取行业指数历史数据
            hist_data = None
            api_functions = [
                # {"name": "sw_index_daily", "args": {"index_code": code}},
                {"name": "index_hist_sw", "args": {"symbol": code}},
                {"name": "sw_index_historical_daily", "args": {"index_code": code}}
            ]
            
            for api_func in api_functions:
                try:
                    func = getattr(ak, api_func["name"])
                    hist_data = func(**api_func["args"])
                    logger.info(f"成功使用{api_func['name']}获取行业数据")
                    break
                except (AttributeError, Exception) as e:
                    logger.warning(f"使用{api_func['name']}获取数据失败: {e}")
                    continue
            
            if hist_data is None or hist_data.empty:
                logger.error(f"所有API方法都失败，无法获取行业{industry_name}的数据")
                return pd.DataFrame()
            
            # 查看数据列名
            logger.info(f"原始数据列名: {hist_data.columns.tolist()}")
            
            # 映射常见的列名格式
            column_maps = [
                # 格式1: 原始API返回的格式
                {
                    "date": "日期",
                    "open": "开盘",
                    "high": "最高",
                    "low": "最低",
                    "close": "收盘",
                    "volume": "成交量",
                    "amount": "成交额"
                },
                # 格式2: 可能的新API格式
                {
                    "日期": "日期",
                    "开盘": "开盘",
                    "最高": "最高",
                    "最低": "最低",
                    "收盘": "收盘",
                    "成交量": "成交量",
                    "成交额": "成交额"
                },
                # 格式3: 另一种可能的格式
                {
                    "trade_date": "日期",
                    "open": "开盘",
                    "high": "最高",
                    "low": "最低",
                    "close": "收盘",
                    "vol": "成交量",
                    "amount": "成交额"
                },
                # 格式4: 另一种可能的格式
                {
                    "index_code": "代码",
                    "datetime": "日期",
                    "open": "开盘",
                    "high": "最高",
                    "low": "最低",
                    "close": "收盘",
                    "volume": "成交量",
                    "amount": "成交额"
                }
            ]
            
            # 根据实际返回的列名选择合适的映射
            applied_map = None
            for column_map in column_maps:
                # 检查是否所有需要映射的列都存在
                mapping_keys = [k for k in column_map.keys() if k in hist_data.columns]
                if mapping_keys:
                    # 只映射存在的列
                    subset_map = {k: column_map[k] for k in mapping_keys}
                    hist_data = hist_data.rename(columns=subset_map)
                    applied_map = subset_map
                    break
            
            if applied_map:
                logger.info(f"应用了列映射: {applied_map}")
            else:
                logger.warning(f"没有找到匹配的列映射，保持原始列名")
                
                # 尝试根据列名含义自动映射
                for col in hist_data.columns:
                    col_lower = col.lower()
                    if 'date' in col_lower or '日期' in col_lower or 'time' in col_lower:
                        hist_data = hist_data.rename(columns={col: '日期'})
                    elif 'open' in col_lower or '开盘' in col_lower:
                        hist_data = hist_data.rename(columns={col: '开盘'})
                    elif 'high' in col_lower or '最高' in col_lower:
                        hist_data = hist_data.rename(columns={col: '最高'})
                    elif 'low' in col_lower or '最低' in col_lower:
                        hist_data = hist_data.rename(columns={col: '最低'})
                    elif 'close' in col_lower or '收盘' in col_lower:
                        hist_data = hist_data.rename(columns={col: '收盘'})
                    elif 'vol' in col_lower or '成交量' in col_lower:
                        hist_data = hist_data.rename(columns={col: '成交量'})
                    elif 'amount' in col_lower or '成交额' in col_lower:
                        hist_data = hist_data.rename(columns={col: '成交额'})
                
                logger.info(f"自动映射后的列名: {hist_data.columns.tolist()}")
            
            # 确保必要的列存在
            required_cols = ['日期', '开盘', '最高', '最低', '收盘']
            missing_cols = [col for col in required_cols if col not in hist_data.columns]
            
            if missing_cols:
                logger.error(f"数据缺少必要的列: {missing_cols}，原始列: {hist_data.columns.tolist()}")
                return pd.DataFrame()
            
            # 确保日期列为正确的日期格式
            if '日期' in hist_data.columns:
                # 打印日期列的类型和前几个值，帮助诊断
                logger.info(f"日期列类型: {type(hist_data['日期'].iloc[0]) if not hist_data.empty else 'Empty DataFrame'}")
                logger.info(f"日期列前5个值: {hist_data['日期'].iloc[:5].tolist() if not hist_data.empty and len(hist_data) >= 5 else hist_data['日期'].tolist()}")
                
                # 处理日期列
                try:
                    # 先将日期列转换为字符串
                    hist_data['日期'] = hist_data['日期'].astype(str)
                    
                    # 然后再转换为datetime类型
                    hist_data['日期'] = pd.to_datetime(hist_data['日期'], errors='coerce')
                    
                    # 检查是否有无效的日期值
                    invalid_dates = hist_data['日期'].isna().sum()
                    if invalid_dates > 0:
                        logger.warning(f"日期转换后有 {invalid_dates} 个无效的日期值，将被过滤")
                        hist_data = hist_data.dropna(subset=['日期'])
                    
                    # 格式化为标准字符串格式
                    hist_data['日期'] = hist_data['日期'].dt.strftime('%Y-%m-%d')
                    logger.info("成功将日期列转换为标准字符串格式")
                except Exception as e:
                    logger.error(f"日期处理失败: {e}")
                    # 尝试不同的日期格式
                    try:
                        # 如果是数值类型，可能是时间戳
                        if pd.api.types.is_numeric_dtype(hist_data['日期']):
                            hist_data['日期'] = pd.to_datetime(hist_data['日期'], unit='ms')
                            hist_data['日期'] = hist_data['日期'].dt.strftime('%Y-%m-%d')
                            logger.info("成功将时间戳转换为日期格式")
                        else:
                            # 如果是其他格式，保持原样并进行筛选
                            logger.warning("无法转换日期格式，使用原始日期格式")
                    except Exception as e2:
                        logger.error(f"处理日期类型失败: {e2}")
            
            # 仅保留所需时间范围的数据
            try:
                # 确保日期列是字符串类型，便于比较
                if not hist_data.empty and '日期' in hist_data.columns:
                    hist_data = hist_data[(hist_data['日期'] >= self.date_start) & (hist_data['日期'] <= self.date_end)]
                    logger.info(f"筛选日期范围后的数据行数: {len(hist_data)}")
            except Exception as e:
                logger.warning(f"按日期筛选数据失败: {e}，使用所有数据")
            
            # 添加成交额列（如果不存在）
            if '成交额' not in hist_data.columns and '成交量' in hist_data.columns:
                # 使用成交量作为替代
                hist_data['成交额'] = hist_data['成交量']
                logger.info("使用成交量值作为成交额")
            
            # 确保所有数值列为浮点数类型
            numeric_cols = ['开盘', '最高', '最低', '收盘', '成交量', '成交额']
            for col in numeric_cols:
                if col in hist_data.columns:
                    try:
                        hist_data[col] = pd.to_numeric(hist_data[col], errors='coerce')
                    except Exception as e:
                        logger.warning(f"转换{col}列为数值类型失败: {e}")
            
            # 按日期排序
            if not hist_data.empty:
                hist_data = hist_data.sort_values('日期')
                logger.info(f"数据已按日期排序，行数: {len(hist_data)}")
            
            # 保存到CSV文件
            file_path = f"{self.data_dir}/{code}_{self.today}.csv"
            save_to_csv(hist_data, file_path)
            logger.info(f"成功获取并保存行业 {industry_name} 的历史数据，共 {len(hist_data)} 条记录")
            
            return hist_data
            
        except Exception as e:
            logger.error(f"获取行业 {industry_name} 历史数据出错: {e}")
            print(f"获取行业 {industry_name} 历史数据出错: {e}")
            return pd.DataFrame()
    
    def analyze_industry(self, industry_code, industry_name):
        """分析单个行业的技术面
        
        Args:
            industry_code: 行业代码
            industry_name: 行业名称
            
        Returns:
            DataFrame: 行业技术分析结果
        """
        logger.info(f"开始分析行业 {industry_name}({industry_code}) 的技术面...")
        print(f"分析行业: {industry_name}")
        
        try:
            # 获取行业历史数据
            hist_data = self.get_industry_history(industry_code, industry_name)
            
            if hist_data is None or hist_data.empty:
                logger.warning(f"行业 {industry_name} 数据获取失败或为空，跳过分析")
                return None
            
            if len(hist_data) < 60:  # 至少需要60个交易日的数据
                logger.warning(f"行业 {industry_name} 数据不足，仅有 {len(hist_data)} 条记录，跳过分析")
                return None
            
            # 确保数值类型正确
            numeric_cols = ['开盘', '最高', '最低', '收盘', '成交量', '成交额']
            hist_data = ensure_numeric(hist_data, numeric_cols)
            
            # 检查数据中是否有无效值
            for col in numeric_cols:
                if col in hist_data.columns and hist_data[col].isna().any():
                    na_count = hist_data[col].isna().sum()
                    if na_count > len(hist_data) * 0.3:  # 如果超过30%的数据缺失
                        logger.warning(f"行业 {industry_name} 的 {col} 列有 {na_count} 个缺失值，可能影响分析质量")
            
            # 计算技术指标
            hist_data = self.tech_analyzer.calculate_all_indicators(hist_data)
            
            # 计算综合得分 - 现在calculate_score会直接在DataFrame中添加得分列
            hist_data = self.tech_analyzer.calculate_score(hist_data)
            
            # 获取最新数据进行分析
            latest_data = hist_data.iloc[-1:].copy()
            
            if latest_data.empty:
                logger.warning(f"行业 {industry_name} 没有最新数据，跳过分析")
                return None
            
            # 添加行业信息
            latest_data['行业代码'] = industry_code
            latest_data['行业名称'] = industry_name
            
            # 添加分析日期
            latest_data['分析日期'] = self.today
            
            # 计算趋势变化（5日涨跌幅）
            if len(hist_data) >= 5:
                try:
                    change_5d = (hist_data['收盘'].iloc[-1] / hist_data['收盘'].iloc[-5] - 1) * 100
                    latest_data['5日涨跌幅'] = round(change_5d, 2)
                except Exception as e:
                    logger.warning(f"计算5日涨跌幅失败: {e}")
                    latest_data['5日涨跌幅'] = np.nan
            
            # 计算趋势变化（20日涨跌幅）
            if len(hist_data) >= 20:
                try:
                    change_20d = (hist_data['收盘'].iloc[-1] / hist_data['收盘'].iloc[-20] - 1) * 100
                    latest_data['20日涨跌幅'] = round(change_20d, 2)
                except Exception as e:
                    logger.warning(f"计算20日涨跌幅失败: {e}")
                    latest_data['20日涨跌幅'] = np.nan
            
            # 添加评级
            latest_data['评级'] = classify_score(latest_data['综合得分'].iloc[0])
            
            logger.info(f"完成行业 {industry_name} 的技术面分析")
            return latest_data
        
        except Exception as e:
            logger.error(f"分析行业 {industry_name} 的技术面出错: {e}")
            print(f"分析行业 {industry_name} 出错: {e}")
            return None
    
    def analyze_all_industries(self):
        """分析所有行业的技术面
        
        Returns:
            DataFrame: 所有行业的技术分析结果
        """
        logger.info("开始分析所有行业的技术面...")
        print("开始分析所有行业的技术面...")
        
        # 获取行业列表
        industry_list = self.get_industry_list()
        
        if industry_list.empty:
            logger.error("获取行业列表失败，无法进行分析")
            print("获取行业列表失败，无法进行分析")
            return pd.DataFrame()
        
        # 分析结果列表
        results = []
        
        # 获取行业代码和名称列
        code_col = None
        name_col = None
        
        for col in industry_list.columns:
            if '代码' in col or 'code' in col.lower():
                code_col = col
            elif '名称' in col or 'name' in col.lower():
                name_col = col
        
        if code_col is None or name_col is None:
            # 如果没有找到合适的列名，使用默认的前两列
            logger.warning(f"无法在行业列表中找到代码和名称列，将使用前两列。可用列: {industry_list.columns.tolist()}")
            code_col = industry_list.columns[0]
            name_col = industry_list.columns[1]
        
        logger.info(f"使用列 '{code_col}' 作为行业代码，'{name_col}' 作为行业名称")
        
        # 遍历行业列表进行分析
        total = len(industry_list)
        print(f"共有 {total} 个行业需要分析")
        
        for idx, row in tqdm(industry_list.iterrows(), total=total, desc="分析行业"):
            industry_code = str(row[code_col])
            industry_name = str(row[name_col])
            
            # 分析单个行业
            result = self.analyze_industry(industry_code, industry_name)
            
            if result is not None and not result.empty:
                results.append(result)
        
        # 合并结果
        if len(results) > 0:
            all_results = pd.concat(results, ignore_index=True)
            
            # 按综合得分降序排序
            all_results = all_results.sort_values(by='综合得分', ascending=False)
            
            # 添加排名
            all_results['排名'] = range(1, len(all_results) + 1)
            
            # 保存到CSV文件
            file_path = f"{self.data_dir}/industry_analysis_{self.today}.csv"
            save_to_csv(all_results, file_path)
            
            logger.info(f"完成所有行业的技术面分析，共分析 {len(all_results)} 个行业")
            print(f"完成所有行业的技术面分析，共分析 {len(all_results)} 个行业")
            
            return all_results
        else:
            logger.warning("没有任何行业分析成功")
            print("没有任何行业分析成功")
            return pd.DataFrame()
    
    def generate_report(self, ranked_industries):
        """生成分析报告
        
        Args:
            ranked_industries: 排名后的行业DataFrame
        """
        if ranked_industries is None or ranked_industries.empty:
            logger.warning("没有行业分析结果，无法生成报告")
            print("没有行业分析结果，无法生成报告")
            return
        
        logger.info("开始生成分析报告...")
        print("开始生成分析报告...")
        
        # 创建HTML报告
        html_report = self._create_html_report(ranked_industries)
        html_file = f"{self.report_dir}/industry_analysis_report_{self.today}.html"
        with open(html_file, 'w', encoding='utf-8') as f:
            f.write(html_report)
        
        # 创建CSV报告
        csv_file = f"{self.report_dir}/industry_analysis_report_{self.today}.csv"
        self._create_csv_report(ranked_industries)
        
        # 创建可视化图表
        self._create_visualization(ranked_industries)
        
        logger.info(f"分析报告生成完成，保存在 {self.report_dir} 目录下")
        print(f"分析报告生成完成，保存在 {self.report_dir} 目录下")
        print(f"HTML报告: {html_file}")
        print(f"CSV报告: {csv_file}")

    def _create_html_report(self, ranked_industries):
        """创建HTML格式的分析报告
        
        Args:
            ranked_industries: 排名后的行业DataFrame
            
        Returns:
            str: HTML报告内容
        """
        try:
            # 创建绝对最简洁的HTML模板，完全不使用CSS样式
            html = """<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>行业股票技术面分析报告</title>
</head>
<body>
    <h1>行业股票技术面分析报告</h1>
    <div>
        <p><strong>分析日期:</strong> {date}</p>
        <p><strong>分析行业数:</strong> {industry_count}</p>
        <p><strong>数据时间范围:</strong> {date_start} 至 {date_end}</p>
    </div>
    
    <h2>行业技术面排名</h2>
    <table border="1">
        <tr>
            <th>排名</th>
            <th>行业代码</th>
            <th>行业名称</th>
            <th>综合得分</th>
            <th>评级</th>
            <th>最新价格</th>
            <th>5日涨跌幅</th>
            <th>20日涨跌幅</th>
        </tr>
{table_rows}
    </table>
    
    <h2>技术面评分说明</h2>
    <p>技术面评分基于以下指标计算:</p>
    <ul>
        <li>MACD指标 (权重: {macd_weight})</li>
        <li>RSI指标 (权重: {rsi_weight})</li>
        <li>KDJ指标 (权重: {kdj_weight})</li>
        <li>布林带指标 (权重: {boll_weight})</li>
        <li>均线系统 (权重: {ma_weight})</li>
        <li>成交量指标 (权重: {volume_weight})</li>
    </ul>
    
    <h2>评级标准</h2>
    <ul>
        <li>强烈推荐: 技术面极强，短中期上涨概率高 (得分 >= {strong_buy})</li>
        <li>推荐: 技术面强势，适合介入 (得分 >= {buy})</li>
        <li>观望: 技术面中性，暂时观望 (得分 >= {hold})</li>
        <li>回避: 技术面弱势，建议规避 (得分 < {hold})</li>
    </ul>
    
    <div>
        <p>行业股票技术面分析工具 - 生成于 {date}</p>
    </div>
</body>
</html>"""
            
            # 生成表格行
            table_rows = ""
            for _, row in ranked_industries.iterrows():
                try:
                    # 提取必要的字段
                    rank = row.get('排名', '')
                    code = row.get('行业代码', '')
                    name = row.get('行业名称', '')
                    score = row.get('综合得分', 0)
                    rating = row.get('评级', '')
                    price = row.get('收盘', 0)
                    change_5d = row.get('5日涨跌幅', 0)
                    change_20d = row.get('20日涨跌幅', 0)
                    
                    # 格式化数值
                    score_formatted = f"{score:.2f}" if pd.notna(score) else "--"
                    price_formatted = f"{price:.2f}" if pd.notna(price) else "--"
                    change_5d_formatted = f"{change_5d:+.2f}%" if pd.notna(change_5d) else "--"
                    change_20d_formatted = f"{change_20d:+.2f}%" if pd.notna(change_20d) else "--"
                    
                    # 添加表格行 - 极简化版本
                    table_rows += f"""        <tr>
            <td>{rank}</td>
            <td>{code}</td>
            <td>{name}</td>
            <td>{score_formatted}</td>
            <td>{rating}</td>
            <td>{price_formatted}</td>
            <td>{change_5d_formatted}</td>
            <td>{change_20d_formatted}</td>
        </tr>\n"""
                except Exception as e:
                    logger.error(f"生成HTML表格行时出错: {e}")
                    continue
            
            # 替换模板中的变量
            html_report = html.format(
                date=self.today,
                industry_count=len(ranked_industries),
                date_start=self.date_start,
                date_end=self.date_end,
                table_rows=table_rows,
                macd_weight=f"{config.WEIGHT_CONFIG['macd']*100:.0f}%",
                rsi_weight=f"{config.WEIGHT_CONFIG['rsi']*100:.0f}%",
                kdj_weight=f"{config.WEIGHT_CONFIG['kdj']*100:.0f}%",
                boll_weight=f"{config.WEIGHT_CONFIG['boll']*100:.0f}%",
                ma_weight=f"{config.WEIGHT_CONFIG['ma']*100:.0f}%",
                volume_weight=f"{config.WEIGHT_CONFIG['volume']*100:.0f}%",
                strong_buy=config.RATING_STANDARDS['strong_buy'],
                buy=config.RATING_STANDARDS['buy'],
                hold=config.RATING_STANDARDS['hold']
            )
            
            return html_report
            
        except Exception as e:
            logger.error(f"创建HTML报告时出错: {e}")
            # 创建极简的错误报告
            error_html = f"""<!DOCTYPE html>
<html>
<head>
<title>报告生成错误</title>
</head>
<body>
<h1>报告生成出错</h1>
<p>生成HTML报告时遇到错误: {e}</p>
<p>查看日志获取详情</p>
</body>
</html>"""
            return error_html

    def _create_csv_report(self, ranked_industries):
        """创建CSV格式的分析报告
        
        Args:
            ranked_industries: 排名后的行业DataFrame
        """
        # 选择需要输出的列
        output_columns = [
            '排名', '行业代码', '行业名称', '综合得分', '评级', '收盘', 
            '5日涨跌幅', '20日涨跌幅', 'MACD得分', 'RSI得分', 'KDJ得分', 
            '布林带得分', '均线得分', '成交量得分', '分析日期'
        ]
        
        # 过滤可用列
        available_cols = [col for col in output_columns if col in ranked_industries.columns]
        
        # 创建报告DataFrame
        report_df = ranked_industries[available_cols].copy()
        
        # 保存为CSV
        csv_file = f"{self.report_dir}/industry_analysis_report_{self.today}.csv"
        save_to_csv(report_df, csv_file)
        
        logger.info(f"CSV报告已保存至 {csv_file}")

    def _create_visualization(self, ranked_industries):
        """创建可视化图表
        
        Args:
            ranked_industries: 排名后的行业DataFrame
        """
        try:
            # 仅选择前10名行业
            top_industries = ranked_industries.head(10).copy()
            
            if top_industries.empty:
                logger.warning("没有足够的数据生成可视化图表")
                return
            
            # 设置图表样式
            plt.style.use('ggplot')
            
            # 创建柱状图
            plt.figure(figsize=config.REPORT_CONFIG['chart_figsize'])
            
            # 准备数据
            industry_names = top_industries['行业名称'].values
            scores = top_industries['综合得分'].values
            
            # 获取每个得分对应的颜色
            colors = [get_score_color(score) for score in scores]
            
            # 绘制柱状图
            bars = plt.barh(industry_names, scores, color=colors)
            
            # 为每个柱添加数值标签
            for bar, score in zip(bars, scores):
                plt.text(bar.get_width() + 1, bar.get_y() + bar.get_height()/2, 
                         f"{score:.1f}", ha='left', va='center')
            
            # 设置图表标题和标签
            plt.title('行业技术面评分排名 (Top 10)', fontsize=16)
            plt.xlabel('综合评分')
            plt.ylabel('行业')
            plt.xlim(0, 105)  # 分数范围0-100，留一点余量
            
            # 保存图表
            chart_file = f"{self.report_dir}/industry_ranking_chart_{self.today}.png"
            plt.tight_layout()
            plt.savefig(chart_file, dpi=config.REPORT_CONFIG['dpi'])
            plt.close()
            
            logger.info(f"排名图表已保存至 {chart_file}")
            
        except Exception as e:
            logger.error(f"创建可视化图表失败: {e}")

def main():
    """主函数"""
    try:
        # 设置日志
        os.makedirs('logs', exist_ok=True)
        
        # 初始化分析器
        analyzer = IndustryAnalysis()
        
        # 分析所有行业并获取排名
        ranked_industries = analyzer.analyze_all_industries()
        
        if not ranked_industries.empty:
            # 生成报告
            analyzer.generate_report(ranked_industries)
            
            # 打印前三名行业
            print("\n========= 技术面最强行业 =========")
            top_count = min(3, len(ranked_industries))
            for i in range(top_count):
                industry = ranked_industries.iloc[i]
                score = industry.get('综合得分', 0)
                rating = industry.get('评级', '未知')
                print(f"{i+1}. {industry['行业名称']} - 评分: {score:.2f}, 评级: {rating}")
        else:
            logger.error("分析失败，未能获取有效的行业数据")
            print("分析失败，未能获取有效的行业数据")
    
    except Exception as e:
        logger.error(f"程序执行出错: {e}")
        print(f"程序执行出错: {e}")

if __name__ == "__main__":
    main() 